//Error Message
const WSERROR               = 1;
const DECODERERROR          = 2;


//Decoder states.
const decoderStateIdle          = 0;
const decoderStateInitializing  = 1;
const decoderStateReady         = 2;
const decoderStateFinished      = 3;

//Player states.
const playerStateIdle           = 0;
const playerStatePlaying        = 1;
const playerStatePausing        = 2;

//Constant.
const maxBufferTimeLength       = 1.0;
const downloadSpeedByteRateCoef = 2.0;


//Window states
const windowStatePlaying        = 1;
const windowStatePausing        = 2;




String.prototype.startWith = function(str) {
  var reg = new RegExp("^" + str);
  return reg.test(this);
};

function FileInfo(url) {
  this.url = url;
  this.size = 0;
  this.offset = 0;
  this.chunkSize = 65536;
}


function Player(opt) {
  this.defaults = {
    /**
       * 回调事件
       */
      // 播放
      onPlaying: null,
      // 暂停
      onPause: null,
      // 结束
      onEnded: null,
      // 错误
      onError: null,
      // 连接超时
      timeoutFun: null,
      // socket关闭
      socketCloseFun: null,
      // 视频打开成功事件
      openVideoSuccess: null,
      // 视频打开失败事件
      openVideoFail: null,
      // 音频打开成功事件
      openAudioSuccess: null,
      // 音频打开失败事件
      openAudioFail: null,
      // 缺少设备回调函数
      onDevicePresentFunc: null,

      // ws连接成功
      onWsSuccess: null,


      mimeCodec: 'video/mp4; codecs="avc1.420028"',
      url: '',
      domId: 'video',
      /**
       * 音频编码类型
       * 8 g726
       * 26 adpcm
       * 1 g721
       */
      codingType: null,
      // 外部提供的数据
      data: null,
      // 视频播放类型
      // 实时 REAL_TIME
      // 回放 TRACK_BACK
      playType: 'REAL_TIME',
      /**
       * 操作类型
       * BOTH_WAY 对讲，UP_WAY 监听，DOWN_WAY 广播
       * 默认对讲
       */
      type: 'BOTH_WAY',

      audioEnabled: false,
      videoEnabled: true,
      recordEnabled: false,
  }

  this.streamInfo = {
    target:1,
    ip:'',
    port:0,
    state:-1,
    timestampStart:0,
    timestampEnd:0,
    message:'',
    sendBytes:0,
    recvBytes:0,
    simNumber:'',
    channel:0,
    uuid:'',
  };


  this._addAssign();

  this.options = Object.assign({}, this.defaults, opt);

  /**
     *  pendingRemoveRanges为source缓存数据清空定时器
     */
   this.pendingRemoveRanges = null;
   /**
    * this.mediaElement为video标签
    */
   this.mediaElement = null;
   /**
    * this.mediaSource为MSE sourceBuffer
    */
   this.mediaSource = null;
   this.websocket = null;
   this.sourceBuffer = null;

  /**
   * 初始化h264转fmp4方法类
   */
  this.fmp4 = null;

  /**
   * 当前页面是否聚焦
   */
  this.pageFocus = true;

  /**
   * 视频是否已经播放
   */
  this.isVideoPlay = false;

  /**
   * create url
   */
  this.mediaSourceObjectURL = null;

  this.startTime = 0;

  /**
  * 视频声音开启状态
  */
  this.audioEnabled = this.options.audioEnabled;
  this.videoEnabled = this.options.videoEnabled;
  this.recordEnabled = this.options.recordEnabled;

  this.rtp = null;

  /**
    * 缓存清理参数
    */
  this.clearFlag = 0;
  this.clearTime = 0;

  /**
    * 空闲超时
    */
  this.freeTimeout = null;

  /**
    * 超时重连计数
    */
  this.timeoutNumber = 0;

  this.isPFrame = 0;

  this.videoCurrentTime = 0;

  this.audioCodec = null;
  this.pcmPlayer = null;
  this.audioRecorder = null;
  this.recvPackageTimeArr = new Array();
  this.payloadTypeAudio = -1;
  this.firstAudioPlayData = true;
  this.firstAudioRecordeData = true;



  this.fileInfo                 = null;
  this.logger                   = new Logger("Player");
  this.currentTimeStamp         = null;
  this.downloadWorker           = null;
  this.parseWorker              = null;
  this.playerState              = playerStateIdle;
  this.frameBuffer              = [];
  this.downloadProto            = kProtoWebsocket;
  this.downloadSeqNo            = 0;
  this.downloading              = false;
  this.mark                     = false;
  this.totalnum                 = 0;
  this.firstAppend              = true;
  this.dataContainer            = new Uint8Array()

  this.initDownloadWorker();
  this.initParseWorker()

  // if (this.videoEnabled) {
  //   this._createMediaSource();
  // }

  // this.audioOpt = {
  //   onDecodeFunc : this._onDecodeDataAudio.bind(this),
  //   onEncodeFunc : this._onEncodeDataAudio.bind(this),
  // };

  // if (this.audioEnabled) {
  //   this.pcmPlayer = new PCMPlayer(1, 8000);
  //   this.audioCodec = new AudioCodec(this.audioOpt);
  // }

  // this.recordOpt = {
  //   onDataFunc : this._onRecordDataAudio.bind(this),
  //   onDevicePresentFunc : this._onDevicePresent.bind(this),
  // };
  // if (this.recordEnabled){
  //   this.audioRecorder = new AudioRecorder(this.recordOpt);
  // }
}

/**
 * 初始化initDownloadWorker
 */
Player.prototype.initDownloadWorker = function () {
  var self = this;
  this.downloadWorker = new Worker('../static/MSEWebsocket/downloader.js')
  this.downloadWorker.onmessage = function (evt) {
      var objData = evt.data;
      switch (objData.t) {
          case kGetFileInfoRsp:
              self.onGetFileInfo(objData.i);
              break;
          case kFileData:
              self.onFileData(objData.d, objData.s, objData.e, objData.q);
              break;
          case kWsError:
              self.onWsError();
              break;
          case kWsSuccess:
              self.onWsSuccess();
              break;
          case kWsReconnect:
              self.onWsReconnect();
              break;
      }
  }
};


Player.prototype.initParseWorker = function () {
  var self = this;
  this.parseWorker = new Worker('../static/MSEWebsocket/parser.js')
  this.parseWorker.onmessage = function (evt) {
      var objData = evt.data;
      switch (objData.t) {
          case kInitParserRsp:
              self.onInitParser(objData);
              break;
          case kVideoFrame:
              self.onVideoFrame(objData);
              break;
          default:
              break;
      }
  }
};

Player.prototype.onInitParser = function (objData) {
  if (objData.e == 0) {
    this.downloadOneChunk()
  } else {
      // this.reportPlayError(objData.e);
  }
}


Player.prototype.onVideoParam = function () {

}

Player.prototype.onAudioFrame = function () {

}

Player.prototype.downloadOneChunk = function () {
  var req = {
    t: kDownloadFileReq,
    u: this.fileInfo.url,
    s: 0,
    e: 0,
    q: this.downloadSeqNo,
    p: this.downloadProto
  }
  this.downloadWorker.postMessage(req);
  this.downloading = true;
}

Player.prototype.changeStreamUrl = function (url) {
  this.fileInfo = new FileInfo(url)

  
  if (this.downloadWorker) {
    this.downloadWorker.postMessage({
        t: kCloseDownloaderReq
    });
  }

  this.downloadOneChunk()
}



Player.prototype.play = function (url, playMode, callback) {
  this.logger.logInfo("Play " + url + ".")


  do {
    if (!url) {
      this.logger.logError("[ER] playVideo error, url empty.");
      break;
    }

    if (!this.downloadWorker) {
      this.logger.logError("[ER] Downloader not initialized.");
      break;
    }

    if (!this.parseWorker) {
      this.logger.logError("[ER] Parser not initialized.");
      break;
    }

    if (url.startWith("ws://") || url.startWith("wss://")) {
        this.downloadProto = kProtoWebsocket;
    } else {
        this.downloadProto = kProtoHttp;
    }

    this.fileInfo = new FileInfo(url);
    this.playerState = playerStatePlaying;

    var req = {
        t: kInitParserReq,
        s: -1,
        c: 102400,
        u: url
    };
    this.parseWorker.postMessage(req);
    // this.downloadOneChunk();
    
    this._createMediaSource();
    // this.displayLoop();

  } while (false);
}


Player.prototype.pause = function (value) {

  this.logger.logInfo("Pause.");

  if (this.downloadWorker) {
    this.downloadWorker.postMessage({
        t: KPauseReq,
        p: value
    });
  }

};

Player.prototype.seekTo = function(settime) {
  
  this.logger.logInfo("SeekTo.");

  if (this.downloadWorker) {
    this.downloadWorker.postMessage({
        t: KSeekToReq,
        s: settime
    });
  }
};

Player.prototype.speed = function (speed) {

  this.logger.logInfo("Speed." + speed);

  if (this.downloadWorker) {
    this.downloadWorker.postMessage({
        t: kSpeedReq,
        s: speed
    });
  }
  if (this.mediaElement) {
    this.mediaElement.playbackRate = Math.pow(2, speed)
  }
}


Player.prototype.singleFrame = function () {

  this.logger.logInfo("singleFrame.");

  if (this.downloadWorker) {
    this.downloadWorker.postMessage({
      t: kSingleFrameReq,
  });
  }
}


Player.prototype.onVideoFrame = function (objData) {
  // if (!this.sourceBuffer || !this.mediaElement) {
  //   this._createMediaSource();
  // }
  if (objData.pts == -1) {
    this.options.onbackTimestamp(0, true);
  } else {
    let rtpFrame = new Result(
      objData.data, 
      objData.media_type, 
      objData.frame_type,
      objData.pts * 1.0 / 90,
      Result.ErrorCode.SUCCESS,
      objData.duration * 1.0 / 90
    );
    
    // this.bufferFrame(rtpFrame)
    this.displayVideoFrame(rtpFrame);
  }
  
};


Player.prototype.bufferFrame = function (rtpFrame) {
  this.frameBuffer.push(rtpFrame);
}



Player.prototype.displayLoop = function () {
  if (this.playerState !== playerStateIdle) {
      requestAnimationFrame(this.displayLoop.bind(this));
  }

  if (this.playerState != playerStatePlaying) {
      return;
  }

  if (this.frameBuffer.length == 0) {
    return;
  }

  this.logger.logInfo("frameBuffer length" + this.frameBuffer.length);

  for (let i = 0; i < 2; ++i) {
    var frame = this.frameBuffer[0];
    if (this.displayVideoFrame(frame)) {
      this.frameBuffer.shift();
    }

    if (this.frameBuffer.length == 0) {
        break;
    }
  }
}


Player.prototype.displayVideoFrame = function (rtpFrame) {
  if (!this.mediaElement || !this.sourceBuffer) {
    return;
  }
  if(rtpFrame.errorCode === Result.ErrorCode.SUCCESS) {
    /**
     * 判断是否是视频数据
     */
    // rtpFrame.duration = rtpFrame.duration == 0 ? 40 : rtpFrame.duration;
    if(rtpFrame.media_type === Result.MediaType.H264)
     {
      if (!this.videoEnabled || !this.sourceBuffer){
        return;
      }
      // console.log('video time='+rtpFrame.time+',duration='+rtpFrame.duration);
      /**
       * 清除视频缓存
       * @type {number}
       */
      if (rtpFrame.frame_type === Result.FrameType.KEY) {
        ++this.clearFlag;
      }

      if (this.options.remoteMode === 2 || this.options.remoteMode === 3) {
        this.isPFrame = 0;
      } else {
        this.isPFrame = 1;
      }
      rtpFrame.duration = this.startTime === 0 ? 0 : (rtpFrame.duration > 0 ?
          rtpFrame.duration : rtpFrame.time - this.startTime);
      if(this.isPFrame === 1)
      {
        rtpFrame.duration = (rtpFrame.duration > 0 && rtpFrame.duration < 2000) ?
            rtpFrame.duration : ((this.startTime === 0 && rtpFrame.duration === 0) ? 0 : 500);
      }

      if(this.sourceBuffer && !this.sourceBuffer.updating) {
        /**
         * 清除视频缓存
         * @type {number}
         */
        if (this.options.playType === 'REAL_TIME') {
          if (this.clearFlag > 10) {
            if(this.clearTime !== 0) {
              this.sourceBuffer.remove(0, this.clearTime);
              if(this.mediaElement.currentTime<this.clearTime) {
                this.mediaElement.currentTime = this.clearTime;
              }
            }
            this.clearTime = this.fmp4.getLastIFrameTime() / 1000;
            this.clearFlag = 0;
          }
        }
        if (this.sourceBuffer && this.mediaElement && this.sourceBuffer.buffered.length>0){
          let startTime = this.sourceBuffer.buffered.start(0);
          let currentTime = this.mediaElement.currentTime;
          if (currentTime - startTime > 60) {
            // 暂时只保留1分钟已播放的缓存
            this.sourceBuffer.remove(0, currentTime - 60);
          }
        }
      }

      if(this.sourceBuffer && !this.sourceBuffer.updating) {
        /**
         * 将H264数据，封装为Fmp4数据，frameDuration为延迟，可通过rtpFrame.time计算
         */
        let fmp4Frame = this.fmp4.makeVideoFrame(rtpFrame, rtpFrame.duration);
        if(fmp4Frame.errorCode === Result.ErrorCode.SUCCESS) {
          this.options.onbackTimestamp(fmp4Frame.time * 1.0 / 1000, false);
          this._doAppendSegments(fmp4Frame.data);
        }
        else {
          /**
           * 封装Fmp4出错，进行错误处理
           */
          // console.error('makeVideoFrame:'+fmp4Frame.errorCode);
          // if (this.options.onErrorFun) {
          //   this.options.onErrorFun(6)
          // }
        }
      }
      else {
        /**
         * MSE对象繁忙，进行缓存
         */
        let result = this.fmp4.saveVideoFrame(rtpFrame, rtpFrame.duration);
        if(result !== Result.ErrorCode.SUCCESS) {
          /**
           * 缓存出错，进行错误处理
           */
          console.error('saveVideoFrame:'+result);
        }
      }
      this.startTime = rtpFrame.time;
    }
  }
  
  return true;
}

Player.prototype.onFileData = function (data, start, end, seq) {
  // this.logger.logInfo("Got data bytes=" + start + "-" + end + ".");

  var objData = {
      t: kFeedDataReq,
      d: data
  };
  this.parseWorker.postMessage(objData);

};

/**
 * websocket成功建立的回调函数
 */
Player.prototype.onWsSuccess = function () {

  if (this.options.onWsSuccess) {
    this.options.onWsSuccess();
  }

  // this._doCleanupSourceBuffer()

  var _this = this;
  document.addEventListener('visibilitychange', this._visibilityEvent.bind(this));

  Player.arr.push(this._visibilitychangeFun.bind(this))
  this.fmp4 = new Fmp4(10 * 1024 * 1024);
}


/**
 * websocket发生错误的回调函数
 * @param {*} error 
 */
Player.prototype.onWsError = function (error) {
  this.streamInfo.message = 'socket error:'+ error;
  if (this.options.onErrorFun) {
    this.options.onErrorFun(WSERROR)
  }
}

Player.prototype.onWsReconnect = function () {
  if (this.options.onReconnect) {
    this.options.onReconnect()
  }
}


Player.prototype._socketClose = function () {

}



Player.prototype.disconnect = function () {
  this.logger.logInfo("disconnect");
  if (this.parseWorker) {
    this.parseWorker.postMessage({
        t: kUninitParserReq
    });
    this.parseWorker.terminate()
  }
  
  if (this.downloadWorker) {
    this.downloadWorker.postMessage({
        t: kCloseDownloaderReq
    });
    this.downloadWorker.terminate()
  }

  // this.clearVideoFrame()
  this.destroy()
};





/**
 * 判断浏览器是否支持Object.assign方法
 * 不支持就进行手动添加
 */
Player.prototype._addAssign = function () {
  if (typeof Object.assign != 'function') {
    Object.defineProperty(Object, "assign", {
      value: function assign(target, varArgs) {
        'use strict';
        if (target == null) {
          throw new TypeError('Cannot convert undefined or null to object');
        }

        var to = Object(target);

        for (var index = 1; index < arguments.length; index++) {
          var nextSource = arguments[index];

          if (nextSource != null) {
            for (var nextKey in nextSource) {
              if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                to[nextKey] = nextSource[nextKey];
              }
            }
          }
        }
        return to;
      },
      writable: true,
      configurable: true
    });
  }
}

/**
 * 判断浏览器是否支持MediaSource和指定要解码播放的视频文件编码和类型
 * @returns {boolean|*}
 */
Player.prototype._isMseSupport = function () {
  return 'MediaSource' in window && MediaSource.isTypeSupported(this.options.mimeCodec);
}

/**
 * 初始化MediaSource
 */
Player.prototype._createMediaSource = function () {
  if (!this._isMseSupport()) {
    throw new Error('浏览器不支持MediaSource或指定的编码类型');
  }
  if (!this.options.domId){
    throw new Error('domId不能为空');
  }

  this.mediaSource = new window.MediaSource();
  /**
   * 如果获取的video状态为未播放状态就替换节点
   */

  let newVideo = document.createElement('video');
  this.mediaElement = document.getElementById(this.options.domId);
  this.mediaElement.setAttribute('data-channel-up', 'true');

  this.mediaSourceObjectURL = window.URL.createObjectURL(this.mediaSource);
  this.mediaElement.src = this.mediaSourceObjectURL;

  /**
    * 给video标签绑定一系列监听事件
    * playing 在媒体开始播放时触发
    * pause 播放暂停时触发
    * ended 播放结束时触发
    * error 发生错误时触发
    */
  this.mediaElement.onplaying = this._onPlaying.bind(this);
  this.mediaElement.onpause = this._onPause.bind(this);
  this.mediaElement.onended= this._onEnded.bind(this);
  this.mediaElement.onerror = this._onError.bind(this);


  /**
    * mediaSource的一系列监听事件
    */
  this.mediaSource.onsourceopen = this._onMediaSourceOpen.bind(this);
  this.mediaSource.onsourceended = this._onMediaSourceEnded.bind(this);
  this.mediaSource.onerror = this._onUpdateError.bind(this);

  /**
    * 判断浏览器类型，调用视频play方法
    */
  this._mediaElementPlay();
}


Player.prototype._mediaElementPlay = function () {
  this.mediaElement.play();
}


Player.prototype._onPlaying = function () {
  if (this.pageFocus) {
    if (this.options.onPlaying) {
      this.options.onPlaying();
    }
  } else {
    this.pageFocus = true;
  }
}

/**
* mediaElement-视频播放暂停时
*/
Player.prototype._onPause = function () {
  if (this.pageFocus) {
    if (this.options.onPause) {
      this.options.onPause();
    }
    // 播放暂停时，保持连接，后台继续获取并解码数据
    // this.websocket.close();
  }
}


/**
 * mediaElement-视频播放结束时
 */
Player.prototype._onEnded = function () {
  if (this.options.onEnded) {
    this.options.onEnded();
  }
  this.closeSocket('End of play!');
}

Player.prototype._onError = function (err) {
  console.log('mediaElement _onError', err);

  // 解码异常, 重新打开
  if (this.options.onErrorFun) {
    this.options.onErrorFun('6');
  }
  // this.destroy();
  // this._createMediaSource();
}


/**
 * mediaSource监听打开事件
 */
Player.prototype._onMediaSourceOpen = function () {
  console.log('onMediaSourceOpen');
  if (!this.sourceBuffer){
    this.sourceBuffer = this.mediaSource.addSourceBuffer(this.options.mimeCodec);
    this.sourceBuffer.onerror = this._onSourceBufferError.bind(this);
    this.sourceBuffer.onupdateend = this._onSourceBufferUpdateend.bind(this);
  }
}

Player.prototype._onMediaSourceEnded = function () {
  console.log('MediaSource onSourceEnded');
}


Player.prototype._onUpdateError = function (error) {
  console.warn(error);
}


Player.prototype._doCleanupSourceBuffer = function () {
  const that = this;
  this.pendingRemoveRanges = setInterval(function () {
    if (that.sourceBuffer) {
      if(!that.sourceBuffer.updating) {
        let buffered = that.sourceBuffer.buffered;
        if (buffered.length > 0) {
          let start = buffered.start(0);
          let end = buffered.end(0);
          try {
            that.sourceBuffer.remove(start, end - 10);
          } catch (err) {
            console.warn(err.message);
          }
        }
      }
    }
  }, 40000);
}

/**
 * source监听错误事件
 */

Player.prototype._onSourceBufferError = function (error) {
  console.log('_onSourceBufferError', error)
}

Player.prototype._onSourceBufferUpdateend = function () {
  if (this.mediaSource && this.mediaSource.readyState === 'open') {
    // console.log('_onSourceBufferUpdateend')
    // this.mediaSource.endOfStream()
  }
}

/**
 * 监听页面是否失去焦点
 * 失去焦点后，页面播放视频暂停
 * 获取焦点后，视频跳转到最新
 */
Player.prototype._visibilitychangeFun = function () {
  const isHidden = document.hidden;
  if (!isHidden) {
    this._videoUpdateTime();
  } else {
    this.pageFocus = false;
  }
}

/**
 * 测试
 * 直接添加视频片段segment
 */
Player.prototype._doAppendSegments = function (segment) {
  if (this.sourceBuffer && !this.sourceBuffer.updating) {
    this.sourceBuffer.appendBuffer(segment);
  }
}

Player.prototype._visibilityEvent = function () {
  this.logger.logInfo("_visibilityEvent");
  Player.arr.forEach(function(ele) {
    ele.call();
  });
}



/**
   * 视频跳转到最新缓存时间点
   */
Player.prototype._videoUpdateTime = function () {
  this.logger.logInfo("_videoUpdateTime");
  if (this.mediaElement && this.sourceBuffer) {
    if (!this.sourceBuffer.updating) {
      if (this.mediaSource.readyState === 'open') {
        this.mediaElement.currentTime = this.sourceBuffer.buffered.end(0);
      }
    }
  }

  if (this.sourceBuffer) {
    let buffered = this.sourceBuffer.buffered;
    if (buffered.length > 0) {
      let start = buffered.start(0);
      let end = buffered.end(0);
      try {
        this.logger.logInfo("_videoUpdateTime remove" + start + "..." + end);
        this.sourceBuffer.remove(start, end - 10);
      } catch (err) {
        // console.warn(err.message);
      }
    }
  }
}




Player.prototype._onDecodeDataAudio = function (pcmFloat32Data, sampleRate, channels) {
  if (this.audioRecorder){
    this.audioRecorder.pushAudioFrameSampleCount(pcmFloat32Data.length*8000/sampleRate);
  }
  if (this.pcmPlayer){
    console.log('onDecodeData2', this.pcmPlayer, channels, sampleRate, pcmFloat32Data)
    this.pcmPlayer.setChannels(channels);
    this.pcmPlayer.setSampleRate(sampleRate);
    this.pcmPlayer.feed(pcmFloat32Data);
  }
}


Player.prototype._onEncodeDataAudio = function (data) {
  let timestamp = this.recvPackageTimeArr.shift();

  let payloadType = this.payloadTypeAudio;
  // aac改为g711a
  if (payloadType == 19){
    payloadType = 6;
  }
  let rtpData = this.rtp.makeAudio(data, timestamp, payloadType);

  if(rtpData.errorCode === Result.ErrorCode.SUCCESS) {
    // 音频片段发送给socket
    if (this.websocket && this.websocket.readyState === 1) {
      this.websocket.send(rtpData.data);
    }
  }
}


Player.prototype._destroyMSE = function () {
  console.log('destroyMSE');

  if (this.mediaSource) {
    if (this.mediaSource.readyState === 'open') {
      try {
        this.sourceBuffer.abort();
      } catch (err) {
        console.log(err.message);
      }
    }

    if (this.mediaSource.readyState !== 'closed') {
      this.mediaSource.removeSourceBuffer(this.sourceBuffer);
    }

    if (this.mediaSource.readyState === 'open') {
      this.mediaSource.endOfStream();
    }

    /**
       * 注销sourceBuffer
       */
     if (this.sourceBuffer) {
      if (this.sourceBuffer.readyState !== undefined) {
        this.mediaSource.removeSourceBuffer(this.sourceBuffer);
      }

      this.sourceBuffer = null;
    }

    /**
      * 注销mediasource
      */
    this.mediaSource = null;

    /**
     * 清空定时器
     */
    if (this.pendingRemoveRanges) {
      clearInterval(this.pendingRemoveRanges);
      this.pendingRemoveRanges = null;
    }
  }

  /**
     * video标签清空src属性
     */
  if (this.mediaElement) {
    this.videoCurrentTime = this.mediaElement.currentTime;
    this.mediaElement.setAttribute('data-currenttime', this.videoCurrentTime);
    console.log('mediaElement', this.mediaElement);
    if (!this.mediaElement.getAttribute('data-video-stop')) {
      this.mediaElement.src = '';
      this.mediaElement.load();
      this.mediaElement.removeAttribute('src');
      this.mediaElement.removeAttribute('data-channel-up');
    }
    this.mediaElement = null;
  }


  if (this.mediaSourceObjectURL) {
    window.URL.revokeObjectURL(this.mediaSourceObjectURL);
    this.mediaSourceObjectURL = null;
  }
}


/**
 * 抓图
 */
Player.prototype.videoScreenshots = function () {
  if (this.mediaElement) {
    //创建canvasu节点
    const canvasElement = document.getElementById(canvasId);
    var canvasCtx = canvasElement.getContext('2d');
    //进行抓图
    canvasCtx.drawImage(this.mediaElement, 0, 0, width, height);

    //转换成图像
    var formData = new FormData();
    canvasElement.toBlob(function(blob){
      formData.append('file', blob);
    });
    return formData;
  }
}

Player.prototype.destroy = function () {
  this._destroyMSE();

  document.removeEventListener('visibilitychange', this._visibilitychangeFun.bind(this));

  this.pageFocus = true;
  this.timeOutMonitoring = null;

  this.startTime = 0;

  this.isPFrame = 0;
  this.videoCurrentTime = 0;
}




/**
 * 开启声音
 */
Player.prototype.openVideoVoice = function () {
  this.firstAudioData = true;
  this.audioEnabled = true;
}

/**
 * 关闭声音
 */
Player.prototype.closeVideoVoice = function () {
  if (this.audioCodec !== null){
    this.audioCodec.destroy();
    this.audioCodec = null;
  }
  if (this.pcmPlayer !== null) {
    this.pcmPlayer.close();
    this.pcmPlayer = null;
  }
  this.audioEnabled = false;
}

/**
 * 空闲超时断开
 */
Player.prototype.freeTimeoutClose = function (time, callback) {
  this.closeFreeTimeout();
  var that = this;

}


Player.prototype.closeFreeTimeout = function () {
  if (this.isOpenFreeTime()) {
    clearTimeout(this.freeTimeout);
    this.freeTimeout = null;
  }
}

Player.prototype.isOpenFreeTime = function () {
  return this.freeTimeout !== null;
}

/**
 * 获取当前的播放时间，相对与开始播放时的时间(单位:s)
 * @returns 
 */
Player.prototype.currentTime = function () {
  if (this.mediaElement){
    return this.mediaElement.currentTime;
  } else {
    return 0;
  }
}

Player.arr = [];